Implement a reversed data transformer for events#4300
Implement a reversed data transformer for events#4300integraledelebesgue wants to merge 1 commit into
Conversation
|
This change is part of the following stack: Change managed by git-spice. |
8e2f690 to
c4c6426
Compare
fa5bba5 to
3e301c1
Compare
c4c6426 to
ac520db
Compare
3e301c1 to
0a8c413
Compare
ac520db to
5e31145
Compare
0a8c413 to
d65be70
Compare
5e31145 to
47429c0
Compare
d65be70 to
5c111fe
Compare
47429c0 to
ffe000a
Compare
5c111fe to
b57024e
Compare
ffe000a to
d6ed44a
Compare
b57024e to
8fceebe
Compare
d6ed44a to
c5d1e90
Compare
8fceebe to
1256e9c
Compare
| fn top_level_typed_events(abi: &[AbiEntry]) -> impl Iterator<Item = &TypedAbiEvent> { | ||
| // All types ever referenced inside any typed event | ||
| let all_types_in_events = abi | ||
| .iter() | ||
| .filter_map(|entry| match entry { | ||
| AbiEntry::Event(AbiEvent::Typed(typed_event)) => Some(typed_event), | ||
| _ => None, | ||
| }) | ||
| .flat_map(|typed_event| match typed_event { | ||
| TypedAbiEvent::Struct(abi_event_struct) => abi_event_struct | ||
| .members | ||
| .iter() | ||
| .map(|field| field.r#type.as_str()) | ||
| .collect::<Vec<_>>(), | ||
| TypedAbiEvent::Enum(abi_event_enum) => abi_event_enum | ||
| .variants | ||
| .iter() | ||
| .map(|field| field.r#type.as_str()) | ||
| .collect::<Vec<_>>(), | ||
| }) | ||
| .collect::<Vec<_>>(); | ||
|
|
||
| // Select only top-level events, i.e. such that are not referenced by other events. | ||
| abi.iter().filter_map(move |entry| match entry { | ||
| AbiEntry::Event(AbiEvent::Typed(typed_event)) | ||
| if !all_types_in_events.contains(&typed_event_name(typed_event)) => | ||
| { | ||
| Some(typed_event) | ||
| } | ||
| _ => None, | ||
| }) | ||
| } |
There was a problem hiding this comment.
nit: Could we use HashSet instead of a Vec for all_types_in_events? Currently, calling .contains() inside the .filter_map closure gives us O(N^2) complexity, while using HashSet, lookup will decrease to O(1).
| self.transform_event_type(&field.r#type, SelectorSource::Consume, db) | ||
| } | ||
| EventFieldKind::Flat => { | ||
| self.transform_event_type(&field.r#type, SelectorSource::None, db) |
There was a problem hiding this comment.
Could this still fail for a valid flattened struct field, e.g. OuterEvent { #[flat] inner: InnerEvent, tail: felt252 }? In that case InnerEvent would not have its own selector in the emitted payload, but here we pass SelectorSource::None and the struct path still seems to require one.
| EventFieldKind::Flat => { | ||
| if self.event_type_matches_selector(&variant.r#type, selector)? { | ||
| return self.transform_event_type( | ||
| &variant.r#type, | ||
| SelectorSource::Provided(selector), | ||
| db, | ||
| ); |
There was a problem hiding this comment.
Could this be lossy for #[flat] enum variants? It looks like we return only the inner decoded event here, without preserving the outer variant wrapper, which might become ambiguous if multiple flat branches match the same selector.
There was a problem hiding this comment.
Could we add a regression test for a directly-emitted typed event that is also referenced as a nested payload in another event? That seems like an edge case behind the top-level filtering logic here.
| } | ||
|
|
||
| /// Transforms a set of event keys and data into a Cairo-like string representation of the event. | ||
| pub fn reverse_transform_event( |
There was a problem hiding this comment.
nit: Could we update to ordering so struct/enums are at the top of file?
Closes #
Introduced changes
Checklist
CHANGELOG.md